﻿
namespace FileStrider
{
    using System;
    using System.Drawing;
    using System.Runtime.InteropServices;

    public static class ShellAPI
    {
        [StructLayout(LayoutKind.Sequential)]
        internal struct SHFILEINFO
        {
            public IntPtr hIcon;
            public IntPtr iIcon;
            public uint dwAttributes;
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)]
            public string szDisplayName;
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 80)]
            public string szTypeName;
        };

        /// <summary>
        /// Retrives system icon 
        /// </summary>
        /// <param name="str">full path of filename, folder or disk</param>
        /// <param name="flags">Flags: </param>
        /// <returns>System icon</returns>
        public static Icon GetIcon(string str, Win32.SHGFI flags)
        {
            ShellAPI.SHFILEINFO shinfo = new ShellAPI.SHFILEINFO();
            IntPtr hIcon;
            hIcon = Win32.SHGetFileInfo(str, 0, ref shinfo, (uint)Marshal.SizeOf(shinfo), (uint)flags);

            if (hIcon != IntPtr.Zero)
            {
                try
                {
                    Icon i = (Icon)System.Drawing.Icon.FromHandle(shinfo.hIcon).Clone();
                    Win32.DestroyIcon(shinfo.hIcon);
                    return i;
                }
                catch
                { return null; }
            }
            else
            { return null; }
        }
    }

    public class Win32
    {
        //public const uint SHGFI_ICON = 0x100;
        //public const uint SHGFI_LARGEICON = 0x0; // 'Large icon
        //public const uint SHGFI_SMALLICON = 0x1; // 'Small icon
        //public const uint SHGFI_SYSICONINDEX = 0x4000;
        //public const uint SHGFI_USEFILEATTRIBUTES = 0x10;

        /// <summary>
        /// Constants for retriving system icons
        /// </summary>
        public enum SHGFI : uint
        {
            SHGFI_ICON              = 0x000000100,     // get icon
            SHGFI_DISPLAYNAME       = 0x000000200,     // get display name
            SHGFI_TYPENAME          = 0x000000400,     // get type name
            SHGFI_ATTRIBUTES        = 0x000000800,     // get attributes
            SHGFI_ICONLOCATION      = 0x000001000,     // get icon location
            SHGFI_EXETYPE           = 0x000002000,     // return exe type
            SHGFI_SYSICONINDEX      = 0x000004000,     // get system icon index
            SHGFI_LINKOVERLAY       = 0x000008000,     // put a link overlay on icon
            SHGFI_SELECTED          = 0x000010000,     // show icon in selected state
            SHGFI_ATTR_SPECIFIED    = 0x000020000,     // get only specified attributes
            SHGFI_LARGEICON         = 0x000000000,     // get large icon
            SHGFI_SMALLICON         = 0x000000001,     // get small icon
            SHGFI_OPENICON          = 0x000000002,     // get open icon
            SHGFI_SHELLICONSIZE     = 0x000000004,     // get shell size icon
            SHGFI_PIDL              = 0x000000008,     // pszPath is a pidl
            SHGFI_USEFILEATTRIBUTES = 0x000000010,     // use passed dwFileAttribute
            SHGFI_ADDOVERLAYS       = 0x000000020,     // apply the appropriate overlays
            SHGFI_OVERLAYINDEX      = 0x000000040      // Get the index of the overlay
        }


        [DllImport("shell32.dll")]
        internal static extern IntPtr SHGetFileInfo(string pszPath, uint dwFileAttributes, ref ShellAPI.SHFILEINFO psfi, uint cbSizeFileInfo, uint uFlags);

        /// <summary>
        /// Provides access to function required to delete handle. This method is used internally
        /// and is not required to be called separately.
        /// </summary>
        /// <param name="hIcon">Pointer to icon handle.</param>
        /// <returns>N/A</returns>
        [DllImport("User32.dll")]
        internal static extern int DestroyIcon(IntPtr hIcon);
    }
}
